Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clear last applied configuration #385

Merged
merged 9 commits into from
Apr 17, 2024

Conversation

mfrancisc
Copy link
Contributor

Copy link

codecov bot commented Apr 5, 2024

Codecov Report

Merging #385 (3004dc4) into master (32311a6) will increase coverage by 0.07%.
The diff coverage is 85.71%.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #385      +/-   ##
==========================================
+ Coverage   77.66%   77.74%   +0.07%     
==========================================
  Files          46       46              
  Lines        1952     1959       +7     
==========================================
+ Hits         1516     1523       +7     
  Misses        376      376              
  Partials       60       60              
Files Coverage Δ
pkg/client/client.go 88.57% <85.71%> (+0.60%) ⬆️

newConfiguration = getNewConfiguration(obj)
// reset the previous config to avoid recursive embedding of the object
if _, found := obj.GetAnnotations()[LastAppliedConfigurationAnnotationKey]; found {
delete(obj.GetAnnotations(), LastAppliedConfigurationAnnotationKey)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather move this to the getNewConfiguration() function. So the function always returns a clean object to be used in the last applied configuration annotation. And also would create a deep copy of the object in that getNewConfiguration() function before modifying it (removing the annotation). It won't break anything in the current code if we don't do it but it would make the function less error prone in case we modify the code in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, done in aacc2c6

I've also added the annotation to the existing obj in unit tests.

@@ -278,7 +287,7 @@ func ApplyUnstructuredObjectsWithNewLabels(ctx context.Context, cl client.Client
for _, unstructuredObj := range unstructuredObjects {
log.Info("applying object", "object_namespace", unstructuredObj.GetNamespace(), "object_name", unstructuredObj.GetObjectKind().GroupVersionKind().Kind+"/"+unstructuredObj.GetName())
MergeLabels(unstructuredObj, newLabels)
_, err := applyClient.ApplyObject(ctx, unstructuredObj)
_, err := applyClient.ApplyObject(ctx, unstructuredObj, SaveConfiguration(false))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately for Unstructured objects it is still not working, so I'm keeping the saveConfiguration functionality disabled. I've tried multiple things:

  • removing the LastAppliedConfigurationAnnotationKey annotation from both new object before creating it
  • removing theLastAppliedConfigurationAnnotationKey annotation from the existing object before merging the annotations with the new object
  • removing the special handling of Unstructured objects in marshalObjectContent:
if newRes, ok := newResource.(runtime.Unstructured); ok {
		return json.Marshal(newRes.UnstructuredContent())
}

but nothing seems to work. The toolchain.dev.openshift.com/last-applied-configuration annotation is still being recursively embedded.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also wondering if we really need this functionality at all. We could

a. trigger the Update of the object anyway , that should do anything if there are no changes on the object.
b. rely on kubectl.kubernetes.io/last-applied-configuration , how is this different from our custom annotation ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good points @mfrancisc. Not sure why we started using our annotation instead. Maybe @MatousJobanek remembers why.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was an attempt to get closer to what kubectl does, to optimize the number of updates we do from our controllers and to have some control over what was updated and what not.
But I really doubt that it works as we hoped that it could work, so I'm for dropping the annotation 👍 to simplify the logic. But let's do it in a separate PR.

Copy link
Contributor

@MatousJobanek MatousJobanek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just some comments related to the tests

@@ -124,6 +124,7 @@ func (c ApplyClient) applyObject(ctx context.Context, obj client.Object, options
namespacedName := types.NamespacedName{Namespace: obj.GetNamespace(), Name: obj.GetName()}
if err := c.Client.Get(ctx, namespacedName, existing); err != nil {
if apierrors.IsNotFound(err) {
obj.SetResourceVersion("") // reset resource version when creating to avoid error: resourceVersion should not be set on objects to be created
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know in which cases the provided object contained the resourceVersion?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was happening with the new toolchaincluster_resource_controller. Unfortunately I don't have the logs anymore but creation of the objects was failing due to this ResourceVersion field being set. TBH I was confused about why this was happening, since the objects should be "new" from the templates directly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't you see the failure as part of the unit tests? see the comment below - it could be the case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't able to reproduce the failure in unit tests. you mean that we should pass a deepcopy of the objects here https://github.com/codeready-toolchain/toolchain-common/pull/385/files#diff-2895f30116602d8fe6b0545c186d4f81247fa4eaab049dab174c6c91c0036e08R291 ? Or something else ..


t.Run("updates of ServiceAccount", func(t *testing.T) {

t.Run("should update service account with last applied configuration", func(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since the "last-appplied-configuration" is used and is set to the same value, then there the SA shouldn't be updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point! I've changed the name of the test in 91ec671. Thank you!

}
existingSA.SetAnnotations(existingLastAppliedAnnotation) // let's set the last applied annotation
cl, cli := newClient(t)
_, err := cl.ApplyRuntimeObject(context.TODO(), existingSA)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that we should pass a deep-copy of the object, otherwise, the generation as well as resourceVersion values would be set and would influence the late execution when the object that is passed to the function again:

Suggested change
_, err := cl.ApplyRuntimeObject(context.TODO(), existingSA)
_, err := cl.ApplyRuntimeObject(context.TODO(), existingSA.DeepCopyObject())

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 91ec671

Copy link

Quality Gate Passed Quality Gate passed

Issues
4 New issues
0 Accepted issues

Measures
0 Security Hotspots
No data about Coverage
10.5% Duplication on New Code

See analysis details on SonarCloud

@mfrancisc mfrancisc merged commit d3c1484 into codeready-toolchain:master Apr 17, 2024
8 checks passed
@mfrancisc mfrancisc deleted the fixlastappliedconfig branch April 17, 2024 08:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants